package com.atguigu.gmall.search.listener;

import com.atguigu.gmall.common.consts.GmallConsts;


import com.atguigu.gmall.pms.entity.*;
import com.atguigu.gmall.search.feign.GmallPmsClient;
import com.atguigu.gmall.search.feign.GmallWmsClient;
import com.atguigu.gmall.search.vo.Goods;
import com.atguigu.gmall.search.vo.SearchAttrVo;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import com.rabbitmq.client.Channel;
import io.jsonwebtoken.lang.Collections;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class MqListener {

    @Autowired
    ElasticsearchRestTemplate restTemplate;

    @Autowired
    GmallPmsClient gmallPmsClient;

    @Autowired
    GmallWmsClient gmallWmsClient;


    /**
     * 监听GmallConsts.SAVE_SPU_QUEUE_NAME消息队列，当queue里面有消息时候，立刻消费
     * 消息内容是pms服务在数据库中新增spu对象时的spuId
     * 拿到spuId后，将新的spu对象封装为goods对象存入到es库中
     * @param spuId
     * @param message
     * @param channel
     */
    @RabbitListener(queues = GmallConsts.SAVE_SPU_QUEUE_NAME)
    //spu保存成功后发送的消息是Long spuId
    public void saveSpuConsumer(Long spuId, Message message, Channel channel) {//接受的消息内容msg是Long类型的spuId
        try {
            //业务代码:根据spuId封装成good,存入es
            System.out.println("接收到" + spuId);
            importSpuToES(spuId);

            //ack确认
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            try {
                if (!message.getMessageProperties().isRedelivered()) {//如果代码是第一次被捕获异常
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                } else {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }


    //业务方法抽取
    //拿到spuId后，将新的spu对象封装为goods对象存入到es库中
    public void importSpuToES (Long spuId){
        SpuEntity spuEntity = gmallPmsClient.querySpuById(spuId).getData();
        //2.1根据spu中的brandID查询品牌
        BrandEntity brandEntity = gmallPmsClient.queryBrandById(spuEntity.getBrandId()).getData();

        //2.2根据spu的category查询分类
        CategoryEntity categoryEntity = gmallPmsClient.queryCategoryById(spuEntity.getCategoryId()).getData();

        //2.3根据spu的id来查询它的检索属性和值
        List<SpuAttrValueEntity> spuAttrValueEntities = gmallPmsClient.queryAttrValueBySpuId(spuEntity.getId()).getData();

        //3.根据spuId查询到sku，遍历sku
        List<SkuEntity> skuEntities = gmallPmsClient.querySkuBySpu(spuEntity.getId()).getData();
        if (Collections.isEmpty(skuEntities)) return;//没有sku直接结束方法
        List<Goods> goodsList = new ArrayList<>();
        for (SkuEntity skuEntity : skuEntities) {   //这里可以封装good对象了,并给其赋值了

            //3.1根据sku的id查询它的检索属性和值
            List<SkuAttrValueEntity> skuAttrValueEntities = gmallPmsClient.queryAttrValueBySkuId(skuEntity.getId()).getData();

            //3.2根据sku的id查询它的库存和销量数据
            List<WareSkuEntity> wareSkuEntities = gmallWmsClient.querySkuWare(skuEntity.getId()).getData();

            //4.创建Good对象，封装数据
            Goods goods = new Goods();

            //sku表所有数据读取
            BeanUtils.copyProperties(skuEntity, goods);
            goods.setSkuId(skuEntity.getId());
            goods.setPrice(skuEntity.getPrice().doubleValue());

            //spu表所有数据读取
            goods.setCreateTime(spuEntity.getCreateTime());

            //wms_ware_sku表所有数据读取
            //用老师的方法，我的注掉吧
            if(!Collections.isEmpty(wareSkuEntities)){
                boolean store = wareSkuEntities.stream().anyMatch(ware -> ware.getStock() - ware.getStockLocked() > 0);//任何一个仓库的库存大于零，则返回true
                goods.setStore(store);
                Long sales = wareSkuEntities.stream().map(WareSkuEntity::getSales).reduce((sale1, sale2) -> sale1 + sale2).get();//所有仓库销量累加就是总销量
                goods.setSales(sales);
            }

            //brand表所有数据读取
            if (brandEntity != null) {
                goods.setBrandId(Long.parseLong(brandEntity.getId()));
                goods.setBrandName(brandEntity.getName());
                goods.setLogo(brandEntity.getLogo());
            }

            //category表所有数据读取
            if (categoryEntity != null) {
                goods.setCategoryId(categoryEntity.getId());
                goods.setCategoryName(categoryEntity.getName());
            }

            //sku_attr_value表，spu_attr_value表数据读取  （检索属性读取）
            List<SearchAttrVo> searchAttrVos = new ArrayList<>();
            if (!Collections.isEmpty(spuAttrValueEntities)) {
                spuAttrValueEntities.forEach(spuAttrValueEntity -> {
                    SearchAttrVo searchAttrVo = new SearchAttrVo();
                    BeanUtils.copyProperties(spuAttrValueEntity, searchAttrVo);
                    //goods.getSearchAttrs().add(searchAttrVo) //老师的方法，回空指针，因为goods.getSearchAttrs是null,不是空集合
                    searchAttrVos.add(searchAttrVo);
                });
            }
            if (!Collections.isEmpty(skuAttrValueEntities)) {
                skuAttrValueEntities.forEach(skuAttrValueEntity -> {
                    SearchAttrVo searchAttrVo = new SearchAttrVo();
                    BeanUtils.copyProperties(skuAttrValueEntity, searchAttrVo);
                    //goods.getSearchAttrs().add(searchAttrVo);//老师的方法，回空指针，因为goods.getSearchAttrs是null,不是空集合
                    searchAttrVos.add(searchAttrVo);
                });
            }
            goods.setSearchAttrs(searchAttrVos);

            //5 将封装好的goods放入goodsList,完成
            goodsList.add(goods);

        }

        //6 将Good对象存入到es中
        restTemplate.save(goodsList);
    }


}
